﻿/**  @author Lokiraze & Phobos	 */
//Double Tap timer issue, dash lasts indefinitely if other movement keys are pressed
//Player can run through part of a wall and get stuck in it with a dash
package Utils
{
//Declarations
	{
		//import flash.ui.Keyboard;
		import adobe.utils.CustomActions;
		import flash.display.Stage;
		import flash.events.KeyboardEvent;
		import flash.filters.ConvolutionFilter;
		import flash.utils.getTimer;
	}
	public class Key
	{
//Variables
		{
			private static var keyDown:Array = new Array(200);			//List to keep track of which keys are being held down or not
			public static var moveOrder:Array = new Array(0);			//Order keys where pressed to continue fluid movement
			
			private static var doubleTapTimer:uint = 200;				//Amount of time before event is considered double tap			
			private static var lastTimeKeyWasPressed:int = 0;			//Time of first key pressed in "double tap" scenario
			private static var lastKeyPressed:int = -1;					//Last key pressed for isDoubleTapped()
			public static var timeCurrentKeyPressed:int = 0;			//Time of second key pressed in "double tap" scenario
			public static var currentKey:uint;							//Used in Inventory.as in KeyHandling()
			public static var isDoubled:Boolean = false;				//Flag for dash function
			public static var dashTimer:uint = 100;						//Amount of time dash is sustained
			
			private static var holdDownTimer:uint = 1000;				//Amount of time before event is considered held down
			private static var timeSinceKeyHeld:uint = 0;				//Time at which last key was pressed
		}
//Event listeners for a key being pressed and released
		public static function Listen(stage:Stage):void						
		{
			stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownListener);
			stage.addEventListener(KeyboardEvent.KEY_UP, KeyUpListener);
			for (var i:Number = 0; i < keyDown.length; i++)
			{
				keyDown[i] = false; //Set keyDown array with all false values
			}
		}
//Determine action when key is pressed down
		private static function KeyDownListener(e:KeyboardEvent):void
		{
	//runs only if key is not being held already
			if (!isDown(e.keyCode))
			{
				currentKey = e.keyCode;								//Inventory.as in KeyHandling()
				keyDown[currentKey] = true;							//Set key in keyDown to register as being held down				
				
				checkMoveKeyTap(currentKey);
				checkActionKeyTap(currentKey);
			}
			checkActionKeyHold(currentKey);
			limitDash();
		}
//Determine action when key is released
		private static function KeyUpListener(e:KeyboardEvent):void
		{			
			keyDown[e.keyCode] = false; //Set key in keyDown to register as not being held
			
			if (isMovementKey(e.keyCode))
			{
				moveOrder.splice(moveOrder.indexOf(e.keyCode),1);	//Remove the key from moveOrder array
			}
		}
//Determine if the key pressed is a movement key
		private static function isMovementKey(keyPressed:uint):Boolean
		{
			switch(keyPressed)
			{
				case DOWN:case LEFT:case RIGHT:
					return true;
				default:
					return false;
			}
		}
//Determine if an action key is being pressed
		private static function isActionKey(keyPressed:uint):Boolean
		{
			switch(keyPressed)
			{
				case X:case C:
					return true;
				default:
					return false;
			}
		}
//Determine if key has been double tapped
		private static function isDoubleTapped(keyPressed:uint):Boolean
		{
			if (lastKeyPressed == keyPressed)
			{
				if (timeCurrentKeyPressed - lastTimeKeyWasPressed < doubleTapTimer)
				{
					trace("double tap");
					lastKeyPressed = -1; //Reset lastKeyPressed so it takes the same double tap key more than once
					return true;
				}
			}
			else
			{
				lastKeyPressed = keyPressed; //Consider keyPressed for being double tapped next cycle
			}
			return false;
		}
//Determine if key is being held down long enough
		private static function isHeld(keyPressed:uint):Boolean
		{
			if (isDown(keyPressed))
			{
				if (getTimer() - timeSinceKeyHeld > holdDownTimer)
				{
					return true;
				}
				return false;
			}
			return false;
		}
//Determine if a movement key is tapped
		private static function checkMoveKeyTap(keyPressed:uint):void
		{
			if (isMovementKey(keyPressed))						//Run if key is a movement key
			{
				timeCurrentKeyPressed = getTimer();				//Reset time of latest keypress
				moveOrder.unshift(keyPressed);					//Add key to moveOrder at top
				if (moveOrder.length == 1)
				{
					isDoubled = isDoubleTapped(keyPressed);		//Check if key is double tapped
				}
				
				lastTimeKeyWasPressed = timeCurrentKeyPressed;	//Reset last key press time to current key press time
			}
		}
//Determine if an action key is tapped
		private static function checkActionKeyTap(keyPressed:uint):void
		{
			if (isActionKey(keyPressed)) //Action Key Tap
			{
				timeSinceKeyHeld = getTimer();						//Set key timer for isHeld()
				switch(keyPressed)
				{
					case C:trace("C Tapped"); break;
					case X:trace("X Tapped"); break;
				}
			}
		}
//Determine if an action key is held down
		private static function checkActionKeyHold(keyPressed:uint):void
		{
			if (isActionKey(keyPressed) && isHeld(keyPressed)) //Action Key Hold
			{
				switch(keyPressed)
				{
					case C:trace("C Held"); break;
					case X:trace("X Held"); break;
				}
			}
		}
//Limits the amount of time for dashing
		private static function limitDash():void
		{
			if (isDoubled)
			{
				if (getTimer() - timeCurrentKeyPressed > dashTimer)
				{
					isDoubled = false;
				}
			}
		}
//Return whether a key is being held down or not
		public static function isDown(k:uint):Boolean
		{
			return keyDown[k];
		}		
//Static Keycodes
		{
			public static var ONE:uint = 49;
			public static var A:uint = 65;
			public static var B:uint = 66;
			public static var BACKSPACE:uint = 8;
			public static var C:uint = 67;
			public static var CAPS_LOCK:uint = 20;
			public static var CTRL:uint = 17;
			public static var D:uint = 68;
			public static var DELETE:uint = 46;
			public static var DOWN:uint = 40;
			public static var E:uint = 69;
			public static var EIGHT:uint = 56;
			public static var END:uint = 35;
			public static var ENTER:uint = 13;
			public static var ESCAPE:uint = 27;
			public static var F:uint = 70;
			public static var F1:uint = 112;
			public static var F10:uint = 121;
			public static var F11:uint = 122;
			public static var F12:uint = 123;
			public static var F13:uint = 124;
			public static var F14:uint = 125;
			public static var F15:uint = 126;
			public static var F2:uint = 113;
			public static var F3:uint = 114;
			public static var F4:uint = 115;
			public static var F5:uint = 116;
			public static var F6:uint = 117;
			public static var F7:uint = 118;
			public static var F8:uint = 119;
			public static var F9:uint = 120;
			public static var FIVE:uint = 53;
			public static var FOUR:uint = 52;
			public static var G:uint = 71;
			public static var H:uint = 72;
			public static var HOME:uint = 36;
			public static var I:uint = 73;
			public static var INSERT:uint = 45;
			public static var J:uint = 74;
			public static var K:uint = 75;
			public static var L:uint = 76;
			public static var LEFT:uint = 37;
			public static var M:uint = 77;
			public static var N:uint = 78;
			public static var NINE:uint = 57;
			public static var NUMPAD_0:uint = 96;
			public static var NUMPAD_1:uint = 97;
			public static var NUMPAD_2:uint = 98;
			public static var NUMPAD_3:uint = 99;
			public static var NUMPAD_4:uint = 100;
			public static var NUMPAD_5:uint = 101;
			public static var NUMPAD_6:uint = 102;
			public static var NUMPAD_7:uint = 103;
			public static var NUMPAD_8:uint = 104;
			public static var NUMPAD_9:uint = 105;
			public static var NUMPAD_ADD:uint = 107;
			public static var NUMPAD_DECIMAL:uint = 110;
			public static var NUMPAD_DIVIDE:uint = 111;
			public static var NUMPAD_ENTER:uint = 108;
			public static var NUMPAD_MULTIPLY:uint = 106;
			public static var NUMPAD_SUBTRACT:uint = 109;
			public static var O:uint = 79;
			public static var P:uint = 80;
			public static var PAGE_DOWN:uint = 34;
			public static var PAGE_UP:uint = 33;
			public static var Q:uint = 81;
			public static var R:uint = 82;
			public static var RIGHT:uint = 39;
			public static var S:uint = 83;
			public static var SEVEN:uint = 55;
			public static var SHIFT:uint = 16;
			public static var SIX:uint = 54;
			public static var SPACE:uint = 32;
			public static var T:uint = 84;
			public static var TAB:uint = 9;
			public static var THREE:uint = 51;
			public static var TWO:uint = 50;
			public static var U:uint = 85;
			public static var UP:uint = 38;
			public static var V:uint = 86;
			public static var W:uint = 87;
			public static var X:uint = 88;
			public static var Y:uint = 89;
			public static var Z:uint = 90;
			public static var ZERO:uint = 48;
		}
	}
}
